using UnityEngine;
using System.Collections;
using System;

public class CreateWalls : MonoBehaviour
{

	public GameObject 	chao;
	public Transform 	parentPiso;
	public GameObject 	parede;
	public Transform 	parentParede;
	public GameObject 	otherCena;
	
	private Vector3		mov;
	private float 		speedCam = 5.0f;
	private int 		largura = 5, comprimento = 5;
	private bool 		configurarTela = false, ativarGridChao = false;
	private Vector3 	primeiroPos;
	private float 		zoom;
	private int 		zoomGrau = 40;

	void Start ()
	{
		mov = transform.position;
		zoom = camera.orthographicSize;
	}
	
	// Update is called once per frame
	void Update ()
	{
		if (configurarTela) {
			CriarChao ();
			DestruirChao ();
			MovCamera ();
		}
	}

	void MovCamera ()
	{
		mov += new Vector3 ((Input.GetAxis ("Horizontal") * Time.deltaTime) * speedCam, 0, (Input.GetAxis ("Vertical") * Time.deltaTime) * speedCam);
		mov.x = Mathf.Clamp(mov.x, -20.5f, 20.5f);
		mov.z = Mathf.Clamp(mov.z, -15.5f, 15.5f);		
		transform.position = mov;
		zoom -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomGrau * Mathf.Abs(zoom);
		zoom = Mathf.Clamp(zoom, 2.5f, 15f);
		camera.orthographicSize = zoom;
	}

	void CriarChao ()
	{
		if (ativarGridChao) {
			if (Input.GetMouseButtonUp (0)) {
				primeiroPos = Vector3.zero;
				GameObject[] pisos = GameObject.FindGameObjectsWithTag ("Chao");
				foreach (GameObject piso in pisos)
					piso.renderer.material.color = new Color (1.0f, 1.0f, 1.0f, 1.0f);
			} else if (Input.GetMouseButtonDown (0)) {
				VerificarChao ();
			} else if (Input.GetMouseButton (0)) {
				VerificarChaoShift ();
			}
		} else if (Input.GetMouseButton (0)) {
			VerificarChao ();
		}
	}

	void VerificarChao ()
	{
		Ray ray = camera.ScreenPointToRay (Input.mousePosition);
		RaycastHit hit;
		if (Physics.Raycast (ray, out hit)) {
			if (hit.transform.tag == "Grid") {
				float x, y, z;
				
				x = ray.origin.x;
				y = 0.01f;
				z = ray.origin.z;
				x = x - (int)x > 0.5f ? (int)x + 1 : x - (int)x < -0.5f ? (int)x - 1 : (int)x;
				z = z - (int)z > 0.5f ? (int)z + 1 : z - (int)z < -0.5f ? (int)z - 1 : (int)z;
				
				Vector3 posicaoCalibrada = new Vector3 (x, y, z);
				GameObject[] pisos = GameObject.FindGameObjectsWithTag ("Chao");
				if (pisos.Length > 0) {
					Vector3[] direcoes = new Vector3[] { Vector3.forward, Vector3.right, Vector3.left, Vector3.back };
					foreach (Vector3 direcao in direcoes) {
						RaycastHit hit2;
						if (Physics.Raycast (posicaoCalibrada, direcao, out hit2, 1.0f)) {
							Debug.DrawRay (posicaoCalibrada, direcao * 1.0f, Color.blue);
							if (hit2.transform.tag == "Chao") {
								GameObject novoChao = Instantiate (chao, posicaoCalibrada, Quaternion.identity) as GameObject;
								novoChao.transform.parent = parentPiso;
							}
						}
					}
				} else {
					GameObject novoChao = Instantiate (chao, posicaoCalibrada, Quaternion.identity) as GameObject;
					novoChao.transform.parent = parentPiso;
				}
				
				if (ativarGridChao)
					primeiroPos = posicaoCalibrada;
			}
		}
	}

	void VerificarChaoShift ()
	{
		Ray ray = camera.ScreenPointToRay (Input.mousePosition);
		RaycastHit hit;
		if (Physics.Raycast (ray, out hit)) {
			if (hit.transform.tag == "Grid") {
				float x, y, z;
				
				x = ray.origin.x;
				y = 0.01f;
				z = ray.origin.z;
				x = x - (int)x > 0.5f ? (int)x + 1 : x - (int)x < -0.5f ? (int)x - 1 : (int)x;
				z = z - (int)z > 0.5f ? (int)z + 1 : z - (int)z < -0.5f ? (int)z - 1 : (int)z;
				
				Vector3 posicaoCalibrada = new Vector3 (x, y, z);
				float xs = primeiroPos.x, zs = primeiroPos.z;
				if (xs > posicaoCalibrada.x)
					xs = posicaoCalibrada.x;
				if (xs < posicaoCalibrada.x)
					xs = posicaoCalibrada.x;
				if (zs > posicaoCalibrada.z)
					zs = posicaoCalibrada.z;
				if (zs < posicaoCalibrada.z)
					zs = posicaoCalibrada.z;
				
				//Debug.Log(xs + " : " + posicaoCalibrada.x + " --- "+ zs + " : " + posicaoCalibrada.z);
				
				for (int newX = (int)primeiroPos.x, newZ = (int)primeiroPos.z; newX < (int)xs && newZ < (int)zs; newX++,newZ++) {
					Vector3 posicaoArray = new Vector3 (newX, y, newZ);
					RaycastHit hit2;
					if (Physics.Raycast (posicaoArray + new Vector3 (0, 0.01f, 0), Vector3.down, out hit2, 1.0f)) {
						Debug.DrawRay (posicaoArray, Vector3.down * 1.0f, Color.blue);
						if (hit2.transform.tag != "Chao") {
							GameObject novoChao = Instantiate (chao, posicaoArray, Quaternion.identity) as GameObject;
							novoChao.transform.parent = parentPiso;
							novoChao.renderer.material.color = new Color (0, 1, 0, 1);
						}
					}
				}
				for (int newX = (int)primeiroPos.x, newZ = (int)primeiroPos.z; newX < (int)xs && newZ < (int)zs; newX++,newZ++) {
					Vector3 posicaoArray = new Vector3 (newX, y, newZ);
					RaycastHit hit2;
					if (Physics.Raycast (posicaoArray + new Vector3 (0, 0.01f, 0), Vector3.down, out hit2, 1.0f)) {
						Debug.DrawRay (posicaoArray, Vector3.down * 1.0f, Color.blue);
						if (hit2.transform.tag != "Chao") {
							GameObject novoChao = Instantiate (chao, posicaoArray, Quaternion.identity) as GameObject;
							novoChao.transform.parent = parentPiso;
							novoChao.renderer.material.color = new Color (0, 1, 0, 1);
						}
					}
				}
				for (int newX = (int)primeiroPos.x; newX < (int)xs; newX++) {
					Vector3 posicaoArray = new Vector3 (newX, y, zs);
					RaycastHit hit2;
					if (Physics.Raycast (posicaoArray + new Vector3 (0, 0.01f, 0), Vector3.down, out hit2, 1.0f)) {
						Debug.DrawRay (posicaoArray, Vector3.down * 1.0f, Color.blue);
						if (hit2.transform.tag != "Chao") {
							GameObject novoChao = Instantiate (chao, posicaoArray, Quaternion.identity) as GameObject;
							novoChao.transform.parent = parentPiso;
							novoChao.renderer.material.color = new Color (0, 1, 0, 1);
						}
					}
				}
				for (int newX = (int)primeiroPos.x; newX > (int)xs; newX--) {
					Vector3 posicaoArray = new Vector3 (newX, y, zs);
					RaycastHit hit2;
					if (Physics.Raycast (posicaoArray + new Vector3 (0, 0.01f, 0), Vector3.down, out hit2, 1.0f)) {
						Debug.DrawRay (posicaoArray, Vector3.down * 1.0f, Color.blue);
						if (hit2.transform.tag != "Chao") {
							GameObject novoChao = Instantiate (chao, posicaoArray, Quaternion.identity) as GameObject;
							novoChao.transform.parent = parentPiso;
							novoChao.renderer.material.color = new Color (0, 1, 0, 1);
						}
					}
				}
				for (int newZ = (int)primeiroPos.z; newZ < (int)zs; newZ++) {
					Vector3 posicaoArray = new Vector3 (xs, y, newZ);
					RaycastHit hit2;
					if (Physics.Raycast (posicaoArray + new Vector3 (0, 0.01f, 0), Vector3.down, out hit2, 1.0f)) {
						Debug.DrawRay (posicaoArray, Vector3.down * 1.0f, Color.blue);
						if (hit2.transform.tag != "Chao") {
							GameObject novoChao = Instantiate (chao, posicaoArray, Quaternion.identity) as GameObject;
							novoChao.transform.parent = parentPiso;
							novoChao.renderer.material.color = new Color (0, 1, 0, 1);
						}
					}
				}
				for (int newZ = (int)primeiroPos.z; newZ > (int)zs; newZ--) {
					Vector3 posicaoArray = new Vector3 (xs, y, newZ);
					RaycastHit hit2;
					if (Physics.Raycast (posicaoArray + new Vector3 (0, 0.01f, 0), Vector3.down, out hit2, 1.0f)) {
						Debug.DrawRay (posicaoArray, Vector3.down * 1.0f, Color.blue);
						if (hit2.transform.tag != "Chao") {
							GameObject novoChao = Instantiate (chao, posicaoArray, Quaternion.identity) as GameObject;
							novoChao.transform.parent = parentPiso;
							novoChao.renderer.material.color = new Color (0, 1, 0, 1);
						}
					}
				}
			}
		}
	}

	void DestruirChao ()
	{
		if (Input.GetMouseButtonUp (1)) {
			Ray ray = camera.ScreenPointToRay (Input.mousePosition);
			RaycastHit hit;
			int chaoSemColisoes = 0;
			if (Physics.Raycast (ray, out hit)) {
				if (hit.transform.tag == "Chao") {
					Transform chaoDestruido = hit.transform;
					Destroy (hit.transform.gameObject);
					Vector3[] direcoes = new Vector3[] { Vector3.forward, Vector3.right, Vector3.left, Vector3.back };
					foreach (Vector3 direcao in direcoes) {
						RaycastHit hit2;
						if (Physics.Raycast (hit.transform.position, direcao, out hit2, 1.0f)) {
							if (hit2.transform.tag == "Chao") {
								Vector3[] direcoes2 = new Vector3[] { Vector3.forward, Vector3.right, Vector3.left, Vector3.back };
								int colisores = 0;
								foreach (Vector3 direcao2 in direcoes2) {
									RaycastHit hit3;
									Debug.DrawRay (hit2.transform.position, direcao2 * 1.0f, Color.blue);
									if (Physics.Raycast (hit2.transform.position, direcao2, out hit3, 1.0f)) {
										if (hit3.transform.tag == "Chao")
											colisores++;
									}
								}
								Debug.Log (colisores);
								if (colisores < 2)
									chaoSemColisoes++;
							}
						}
					}
					Debug.Log (chaoSemColisoes);
					if (chaoSemColisoes > 0) {
						GameObject novoChao = Instantiate (chao, chaoDestruido.position, chaoDestruido.rotation) as GameObject;
						novoChao.transform.parent = parentPiso;
					}
				}
			}
		}
	}

	void OnGUI ()
	{
		if (!configurarTela)
			EstruturaInicialGUI ();
		else {
			ModoEdicaoGUI ();
		}
	}

	void EstruturaInicialGUI ()
	{
		if (GUI.Button (new Rect (90, 90, 60, 25), "OK")) {
			GetChao (comprimento, largura);
		}
		
		GUI.Label (new Rect (10, 15, 100, 25), "Comprimento: ");
		string sComprimento = GUI.TextField (new Rect (110, 15, 50, 25), comprimento + "");
		if (sComprimento != null && sComprimento != "")
			comprimento = Int32.Parse (sComprimento);
		else
			comprimento = 0;
		GUI.Label (new Rect (10, 50, 100, 25), "Largura: ");
		string sLargura = GUI.TextField (new Rect (110, 50, 50, 25), largura + "");
		if (sLargura != null && sLargura != "")
			largura = Int32.Parse (sLargura);
		else
			largura = 0;
	}

	void ModoEdicaoGUI ()
	{
		if (GUI.Button (new Rect (10, 10, 120, 20), "Colocar Paredes")) {
			GetParedes ();
		}
		
		ativarGridChao = GUI.Toggle (new Rect (10, 60, 120, 20), ativarGridChao, "Grid Chao");
	}

	void GetChao (int comprimento, int largura)
	{
		for (int z = 0; z < comprimento; z++) {
			for (int x = 0; x < largura; x++) {
				GameObject novoChao = Instantiate (chao, Vector3.zero, Quaternion.identity) as GameObject;
				novoChao.transform.parent = parentPiso;
				novoChao.transform.position = new Vector3 (x - (int)(largura / 2), 0.01f, z - (int)(comprimento / 2));
			}
		}
		configurarTela = true;
	}

	void GetParedes ()
	{
		GameObject[] antigasParedes = GameObject.FindGameObjectsWithTag ("Parede");
		if (antigasParedes.Length > 0) {
			foreach (GameObject parede in antigasParedes)
				Destroy (parede);
		}
		
		GameObject[] pisos = GameObject.FindGameObjectsWithTag ("Chao");
		if (pisos.Length > 0) {
			foreach (GameObject piso in pisos) {
				Vector3[] direcoes = new Vector3[] { Vector3.forward, Vector3.right, Vector3.left, Vector3.back };
				foreach (Vector3 direcao in direcoes) {
					RaycastHit hit;
					if (!Physics.Raycast (piso.transform.position, direcao, out hit, 1.0f)) {
						Vector3 posicaoParede;
						GameObject novaParede;
						if (direcao == Vector3.forward) {
							posicaoParede = piso.transform.position + new Vector3 (0, 0, 0.5f);
							novaParede = Instantiate (parede, posicaoParede, parede.transform.rotation) as GameObject;
							novaParede.transform.parent = parentParede;
							novaParede.transform.eulerAngles += new Vector3 (0, 90.0f, 0);
						}
						if (direcao == Vector3.right) {
							posicaoParede = piso.transform.position + new Vector3 (0.5f, 0, 0);
							novaParede = Instantiate (parede, posicaoParede, parede.transform.rotation) as GameObject;
							novaParede.transform.parent = parentParede;
							novaParede.transform.eulerAngles += new Vector3 (0, 180.0f, 0);
						}
						if (direcao == Vector3.left) {
							posicaoParede = piso.transform.position + new Vector3 (-0.5f, 0, 0);
							novaParede = Instantiate (parede, posicaoParede, parede.transform.rotation) as GameObject;
							novaParede.transform.parent = parentParede;
						}
						if (direcao == Vector3.back) {
							posicaoParede = piso.transform.position + new Vector3 (0, 0, -0.5f);
							novaParede = Instantiate (parede, posicaoParede, parede.transform.rotation) as GameObject;
							novaParede.transform.parent = parentParede;
							novaParede.transform.eulerAngles = new Vector3 (270, 0, 0);
						}
					}
				}
			}
			GameObject[] paredesNovas = GameObject.FindGameObjectsWithTag ("Parede");
			if (paredesNovas.Length > 0) {
				foreach (GameObject parede in paredesNovas)
					parede.collider.enabled = true;
			}
			
			otherCena.active = true;
			gameObject.active = false;
		} else {
			Debug.LogWarning ("Não existe chão! Por isso não pode ser criado paredes.");
		}
	}
}
